home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 5074 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  11.2 KB

  1. Path: solon.com!not-for-mail
  2. From: seebs@solutions.solon.com (Peter Seebach)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: Schildt <- Advanced Books
  5. Date: 11 Feb 1996 11:23:45 -0600
  6. Organization: Usenet Fact Police (Undercover)
  7. Message-ID: <4fl8n1$n2@solutions.solon.com>
  8. References: <8BA8405.02C70020DE.uuout@sourcebbs.com>
  9. NNTP-Posting-Host: solutions.solon.com
  10.  
  11. In article <8BA8405.02C70020DE.uuout@sourcebbs.com>,
  12. DAVID MOHORN <david.mohorn@sourcebbs.com> wrote:
  13. >The only book that I know of that uses the notorious void main(void) is
  14. >his "Teach Yourself C" book.  But he only uses this for the first half
  15. >of the book.  This is only because he doesn't want the reader to be
  16. >overwhelmed with all the data types and other things until he has a
  17. >chance to explain how functions return values and pass arguments.
  18.  
  19. How about "C: The Complete Reference" - *the entire book*.
  20.  
  21. Everywhere in it, and he even claims that it's legal (page 163, in the
  22. 3rd edition.)
  23.  
  24. [Re: C: TCR]
  25.  
  26. >I think it is a great reference!!!  Now if Schildt will just write a
  27. >"Teach Yourself Assembler" book that blows Mark Goodwin's book away.
  28. >This book really stunk.  It was nothing more than the User Guide that
  29. >comes with the Assembler.  YUCK!
  30.  
  31. I think it is a horrid reference.  It makes *many* mistakes, several of
  32. them stupid.  I'll append my (incomplete) list.  Look through this list,
  33. and try to tell me *none* of these are a problem in a reference manual.
  34. I think all of them are at least moderately bad.
  35.  
  36. >M>Born To Code In C develops a multi-threaded program! That's
  37. > >as advanced as you can get. In DOS, way before multi-threaded OSes
  38. > >like NT and OSF/1 came out.
  39.  
  40. >I agree.
  41.  
  42. Nothing advanced about it; I wrote multithreaded programs before I knew what
  43. they were.  He doesn't *understand* advanced topics; he programs by luck
  44. and cut-n-paste, without understanding why things work.  (You can tell; if
  45. he understood, he'd explain them correctly, rather than making
  46. curious but irrelevant statements.)
  47.  
  48. >This would be great.  I see his "Teach Yourself C" is not in its 2nd
  49. >Edition.
  50.  
  51. Yup.  And the third edition managed to correct typos without correcting
  52. errors.  The most visibly *stupid*, imho, is the one on page 53 (see
  53. included text) having to do with sizeof.  It's never been right, I have
  54. never even *heard* of a machine where it could be right, and he even
  55. contradicts it later on.  (Correctly so, I might add.)
  56.  
  57. [Begin included text.]
  58. I am not including "bad style", but there are a few of those (gets is
  59. strongly depracated, and many programs don't output the last newline,
  60. probably because MS-DOS prints an extra one before the prompt.)
  61.  
  62. Please pardon typos, and even the possible errors; I have not taken the time
  63. to verify a couple of things.  For a serious, aimed-at-publication effort,
  64. I would, of course, take the time to bring the questionable points to the
  65. attention of people in comp.std.c, or otherwise cross-reference the work.
  66. As is, I'm just using memory and the Standard to compare.
  67.  
  68. Flat contradictions of ANSI's standard.
  69.  
  70.     Page 163
  71.  
  72.         "You may also declare main() as void if it does
  73.          not return a value."
  74.  
  75.     Specifically untrue.  ANSI mandates two declarations for main, and
  76.     says that main may have declarations compatible with those.  Both
  77.     return int.
  78.  
  79.     Page 434
  80.  
  81.         "free() must only be called with a pointer that was
  82.          previously allocated with one of the dynamic allocation
  83.          system's functions (either malloc(), realloc(), or
  84.          calloc())."
  85.  
  86.     Also specifically untrue.  ANSI states that free(NULL) is legal and
  87.     has no effect.  (Also note that it must be called with a pointer
  88.     *to space previously allocated*, not with a pointer previously
  89.     allocated, and that the pointer must not have been already freed
  90.     or passed to realloc().)
  91.  
  92.     Page 314
  93.  
  94.         "However, since EOF is a valid integer value, you must use
  95.          feof() to check for end-of-file when working with binary
  96.          files."
  97.  
  98.     Not merely a little bit untrue, but utterly wrong, and specifically
  99.     missing the point of the rule (correctly stated) about returning
  100.     the char as "unsigned char converted to int" (actually stated
  101.     in the standard in 7.9.7.1, under fgetc()).
  102.  
  103.     Since EOF is a *NEGATIVE* integral constant, it can *NEVER* compare
  104.     equal to *ANY* unsigned char.  When you are reading from a binary
  105.     file, the values you get will *never* compare equal to EOF, until
  106.     getchar() returns EOF because the file is empty.
  107.  
  108.     This correlates with a mistake made in all of the examples where
  109.     loops break on '$', 'A', or ' ' because the return from getchar() is
  110.     immediately put into a char variable.
  111.  
  112.     This is a more serious flaw than many, because it results in poorly
  113.     written, inefficient code.
  114.  
  115.     (Couple this with the consistent attempts to use feof() to see if
  116.     the *next* read will fail, when in fact feof() only returns true
  117.     when the *PREVIOUS* read failed, and you get a completely wrong
  118.     description of the standard I/O library.)
  119.  
  120.     Also, several of the programs given loop forever if an end of
  121.     file is reached, because EOF is not checked for in a loop.
  122.  
  123.     (The astute reader will note that he is correct for implementations
  124.     in which char and int are the same size; I disregard this because:
  125.         1.  This violates the spirit, if not the letter, of the
  126.             standard.
  127.         2.  The implementation he is discussing does not have this
  128.             problem.
  129.     In such an environment, the "correct" thing to do is probably to
  130.     use fread and check for failure.  feof() will still not warn you that
  131.     your next read will fail.)
  132.  
  133.     Page 284
  134.  
  135.     All of the header files are listed in capitals; the standard
  136.     specifies them in lower case.  It is not required that a
  137.     C compiler reject all-caps, but nor is it required that it
  138.     accept them.
  139.  
  140. Flat contradictions of POSIX, in the discussion of open/read/write.
  141.  
  142.     Page 253
  143.  
  144.         "In most implementations, the operation fails if the file
  145.          specified in the open statement does not exist on the disk."
  146.  
  147.     To the best of my knowledge, POSIX (the standard for the open()
  148.     call) documents and requires the functionality of the O_CREAT flag.
  149.  
  150. Undefined behavior/illegal code.
  151.  
  152.     Page 247
  153.  
  154.     The stream fp is opened with mode "r", the mode to open a text file.
  155.     Then, fseek is called on fp, with the 2nd argument not a value
  156.     returned by a previous call to ftell. (ANSI 7.9.9.2, "For a text
  157.     stream, either offset shall be zero, or offset shall be a value
  158.     returned by an earlier call to the ftell function on the same stream
  159.     and whence shall be SEEK_SET.")
  160.  
  161.     Page 63
  162.  
  163.     If scanf fails, the variable guess is referenced before it has been
  164.     initialized; accessing an uninitialized object introduces
  165.     undefined behavior.
  166.  
  167.     Page 283
  168.  
  169.         >#include <string.h>
  170.         >
  171.         >char s1[] = "hello ";
  172.         >char s2[] = "there.";
  173.         >
  174.         >void main(void)
  175.         >{
  176.         >  int p;
  177.         >
  178.         >  p = strcat(s1, s2);
  179.         >}
  180.  
  181.     It is correctly noted that this generates a warning.  Not mentioned
  182.     is that it's illegal; although s1[] is a modifiable array, it is
  183.     an array large enough to hold "hello " (and the terminating NUL),
  184.     so it has room for 7 bytes.  The strcat overflows the array, producing
  185.     undefined behavior.
  186.  
  187.     Page 735
  188.  
  189.     This is spectacularly wrong; the "corrected"
  190.  
  191.         "x = *p * (*p++);"
  192.  
  193.     is *EXACTLY* equivalent in terms of C; as correctly noted earlier,
  194.     the order of evaluation *IS NOT SPECIFIED*.
  195.  
  196.     The code is still illegal (p is used to determine *p on the left
  197.     of the *, as well as modified on the right), and the parentheses
  198.     aren't affecting the code at all.
  199.  
  200.     In this code, p can be incremented anywhere in the line; the only
  201.     requirement would be that the value of (*p++) be the same as
  202.     the value of (*p) before the increment.  It is *not* specified
  203.     whether the other *p happens before or after the increment.
  204.  
  205.     In fact, because the code modifies an object (p) and uses the value
  206.     of the object to do something other than determine the new value
  207.     (The first "*p"), it is *illegal*.  Completely; a compiler is allowed
  208.     to reject the code, and many will produce surprising results from
  209.     this operation.
  210.  
  211.     This is not merely wrong, it's wrong *while discussing the problem*,
  212.     which is doubly bad.
  213.  
  214. Code which does not do what it says it does.
  215.  
  216.     Page 333
  217.  
  218.     After
  219.  
  220.         >char str[80];
  221.         >
  222.         >sprintf(str,"%s %d %c", "one", 2, 3);
  223.  
  224.     it is asserted that str will contain "one 2 3".  This is incorrect;
  225.     it would contain "one 2 ^C".
  226.  
  227.     Page 53
  228.  
  229.         >printf("%f", sizeof f);
  230.  
  231.     Clearly wrong; sizeof is not a double or float.
  232.  
  233.     Page 53
  234.  
  235.         >printf("%d", sizeof(int));
  236.  
  237.     Subtly wrong; sizeof is a size_t, which may not be any sort of int.
  238.     The only safe way to do this is
  239.  
  240.         >printf("%lu", (unsigned long) sizeof(int));
  241.  
  242.     While this is larger, a clear explanation of why it is required will
  243.     go a long way towards helping people understand C.
  244.  
  245.     Page 53 (This one's popular)
  246.  
  247.         >/* Write 6 integers to a disk file. */
  248.         >void put_rec(int rec[6], FILE *fp)
  249.         >{
  250.         >  int len;
  251.         >
  252.         >  len = fwrite(rec, sizeof rec, 1, fp);
  253.         >  if (len != 1) printf("write error");
  254.         >}
  255.  
  256.     Incorrect.  As correctly noted elsewhere, when "int rec[6]" is an
  257.     argument to a function, it actually specifies a pointer-to-int,
  258.     not an array[6]-of-int.  sizeof rec is sizeof(int *) here, and this
  259.     code works only if sizeof(int *) is precisely 6 times sizeof(int).
  260.     (Not impossible, but hardly likely.)
  261.  
  262.     Further, who said fp was a disk file?  fp could be stdout.
  263.  
  264. Inaccurate or misleading explanations.
  265.  
  266.     Page 132
  267.  
  268.         "After the assignment, p points to the first 1000 bytes of
  269.          free memory."
  270.  
  271.     No, p points to at least 1000 bytes of allocated space, which is
  272.     not free memory.  There is also no reason to assume it was the
  273.     "first" 1000 bytes; top-down allocation is not atypical, and
  274.     further, there's no reason to assume this code fragment runs in
  275.     isolation.
  276.  
  277.     Page 197
  278.  
  279.     It is redundant to give a size of char in bytes as 1 as an
  280.     "assumption" - it's the definition, sizeof() gives the size
  281.     in *chars*.
  282.  
  283.     Page 162
  284.  
  285.     Functions are not of type void; functions are of various types,
  286.     called collectively the function types.  A function may have a
  287.     return of type void, which means that its type is something like
  288.     "function taking (...) and returning void".
  289.  
  290.     Page 59
  291.  
  292.         "This shorthand works for all the binary operators..."
  293.  
  294.     No, it doesn't.  It doesn't work for ".", "->", "&&", or "||".
  295.  
  296.     Page 33
  297.  
  298.         "static Global Variables" [heading]
  299.  
  300.     No such thing.  A static variable outside of a function has file
  301.     scope, which is distinct from global scope.
  302.  
  303. Explanations of a DOS-specific feature as "how C works".
  304.  
  305.     Page 19
  306.  
  307.         "In general, negative numbers are represented using the
  308.          two's complement approach..."
  309.  
  310.     This is not a C feature.  It is a common implementation, but it is
  311.     specifically not required.
  312.  
  313.     Page 131
  314.  
  315.         "Memory allocated by C's dynamic allocation functions is
  316.          obtained from the <i>heap</i> -- the region of free memory
  317.          that lies between your program and its permanent storage
  318.          area and the stack."
  319.  
  320.     C does not specify that there is a stack - only that functions can
  321.     call each other.  The "heap" is a DOS term, and the layout is not
  322.     a part of the C language.  It is not atypical for the layout to be
  323.     radically different, and certainly, there is no call for describing
  324.     a specific choice as "what happens".
  325. -- 
  326. Peter Seebach - seebs@solon.com - Copyright 1995 Peter Seebach.
  327. C/Unix wizard -- C/Unix questions? Send mail for help.  No, really!
  328. FUCK the communications decency act.  Goddamned government.  [literally.]
  329. The *other* C FAQ - ftp taniemarie.solon.com /pub/c/afq - Not A Flying Toy
  330.